package top.akame.webs.controller

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.util.Base64Utils
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.multipart.MultipartFile
import top.akame.utils.FFMpegs
import top.akame.webs.utils.RestResponse
import top.akame.webs.utils.Uploads
import java.io.File
import javax.servlet.http.HttpServletRequest
import kotlin.math.sign

/**
 * @AUTHOR soft
 * @DATE 2019/6/26 2:30
 * @DESCRIBE
 */
@RestController
class FileController {

    @Value("\${ffmpeg.temp}")
    lateinit var temp: String

    @Value("\${ffmpeg.output}")
    lateinit var output: String

    @Value("\${ffmpeg.path}")
    lateinit var ffmpeg: String

    @Autowired
    lateinit var uploads: Uploads

    lateinit var ffMpegs: FFMpegs

    lateinit var request: HttpServletRequest

    @ModelAttribute
    fun init(request: HttpServletRequest) {
        ffMpegs = FFMpegs(FFPath = ffmpeg, FFTemp = temp, FFOut = output)
        this.request = request
    }

    /**
     * 探测请求 查看这个文件上传的状态 为了实现断点续传
     * @param flag 文件唯一标识 前端传过来的 一般是md5值
     */
    @PostMapping("/probe")
    fun probe(flag: String): RestResponse {
        val file1 = File(output, flag) // 已经上传完成 返回各种访问地址
        if (file1.exists()) {
           return this.info(Base64Utils.encodeToUrlSafeString(flag.toByteArray()))
        }

        val file = File(temp, flag)
        var stats = 0
        if (file.exists() && file.isDirectory) {
            stats = uploads.getStats(flag)
        }
        return RestResponse.ok(mapOf("stats" to stats, "flag" to flag))
    }

    /**
     * 文件上传
     * 支持分片上传
     *
     * @param flag  当前上传文件的唯一标识 md5值最好
     * @param stats 当前上传文件的块数位置 从0开始
     * @param total 文件总块数
     */
    @PostMapping("/upload")
    fun upload(@RequestParam("file") mlFile: MultipartFile, flag: String,
               @RequestParam(defaultValue = "0", required = false) stats: Int,
               @RequestParam(defaultValue = "1", required = false) total: Int): RestResponse {
        if (stats + 1 < total) {
            uploads.saveToTemp(mlFile, flag)
            val r = (stats + 1.0) / total

            uploads.markStats(flag, stats + 1)
            return RestResponse.fail(mapOf("progress" to r))
        } else {
            val toTemp = uploads.saveToTemp(mlFile, flag)
            val m3u8 = ffMpegs.mp4ToM3u8(toTemp, flag)
            uploads.clearTemp(flag)
            val host = host()
            val m38b = Base64Utils.encodeToUrlSafeString(m3u8.toByteArray())

            return RestResponse.ok(mapOf("progress" to 1.0,
                    "video" to "$host/?f=$m38b",
                    "m3u8" to "$host/v1/$m3u8/index.m3u8",
                    "cover" to "$host/v1/$m3u8/cover.png",
                    "sign" to m38b))
        }
    }

    @PostMapping("/info")
    fun info(sign: String): RestResponse {
        val host = host()
        val m3u8 = String(Base64Utils.decodeFromUrlSafeString(sign))
        return RestResponse.ok(mapOf(
                "video" to "$host/?f=$sign",
                "m3u8" to "$host/v1/$m3u8/index.m3u8",
                "cover" to "$host/v1/$m3u8/cover.png",
                "sign" to sign))
    }

    fun host(): String {
        val url = request.requestURL
        return url.substring(0, url.lastIndexOf("/"))
    }
}
